/*
 * Copyright (C), 2015-2018
 * FileName: com.lizhaoblog.hundredone.Solution013
 * Author:   zhao
 * Date:     2018/7/20 21:56
 * Description: 第十三题
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.lizhaoblog.hundredone;

import java.util.HashMap;
import java.util.Map;

/**
 * 〈一句话功能简述〉<br>
 * 〈第十三题〉
 *
 * @author zhao
 * @date 2018/7/20 21:56
 * @since 1.0.0
 */
public class Solution013 {
  /*********************
   * 题目
   * 罗马数字包含以下七种字符：I， V， X， L，C，D 和 M。
   *
   * 字符          数值
   * I             1
   * V             5
   * X             10
   * L             50
   * C             100
   * D             500
   * M             1000
   * 例如， 罗马数字 2 写做 II ，即为两个并列的 1。12 写做 XII ，即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。
   *
   * 通常情况下，罗马数字中小的数字在大的数字的右边。但也存在特例，例如 4 不写做 IIII，而是 IV。数字 1 在数字 5 的左边，所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地，数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况：
   *
   * I 可以放在 V (5) 和 X (10) 的左边，来表示 4 和 9。
   * X 可以放在 L (50) 和 C (100) 的左边，来表示 40 和 90。
   * C 可以放在 D (500) 和 M (1000) 的左边，来表示 400 和 900。
   * 给定一个罗马数字，将其转换成整数。输入确保在 1 到 3999 的范围内。
   *
   * 示例 1:
   *
   * 输入: "III"
   * 输出: 3
   * 示例 2:
   *
   * 输入: "IV"
   * 输出: 4
   * 示例 3:
   *
   * 输入: "IX"
   * 输出: 9
   * 示例 4:
   *
   * 输入: "LVIII"
   * 输出: 58
   * 解释: C = 100, L = 50, XXX = 30, III = 3.
   * 示例 5:
   *
   * 输入: "MCMXCIV"
   * 输出: 1994
   * 解释: M = 1000, CM = 900, XC = 90, IV = 4.
   */

  /**************************************
   * 我的做法
   * 超过88.68%的测试案例
   *
   * ***********************************/
  public int romanToInt(String s) {
    Map<Character, Integer> map = new HashMap();
    map.put('I', 1);
    map.put('V', 5);
    map.put('X', 10);
    map.put('L', 50);
    map.put('C', 100);
    map.put('D', 500);
    map.put('M', 1000);

    int sum = 0;
    char[] charArr = s.toCharArray();
    for (int i = 0; i < charArr.length; i++) {
      int value = map.get(charArr[i]);

      if (i < charArr.length - 1) {
        int tmpValue = checkExp(charArr[i], charArr[i + 1]);
        if (tmpValue > 0) {
          value = tmpValue;
          i++;
        }
      }
      sum += value;
    }
    return sum;
  }

  private int checkExp(char c, char nextChar) {
    int result = 0;
    switch (c) {
      case 'I':
        if (nextChar == 'V') {
          result = 4;
        } else if (nextChar == 'X') {
          result = 9;
        }
        break;
      case 'X':
        if (nextChar == 'L') {
          result = 40;
        } else if (nextChar == 'C') {
          result = 90;
        }
        break;
      case 'C':
        if (nextChar == 'D') {
          result = 400;
        } else if (nextChar == 'M') {
          result = 900;
        }
        break;
      default:
        break;
    }
    return result;

  }

  /**************************************
   * 比我好的答案
   * ***********************************/
  public int betterRomanToInt(String s) {
    Map<Character, Integer> map = new HashMap();
    map.put('I', 1);
    map.put('V', 5);
    map.put('X', 10);
    map.put('L', 50);
    map.put('C', 100);
    map.put('D', 500);
    map.put('M', 1000);

    int sum = 0;
    char[] charArr = s.toCharArray();
    for (int i = 0; i < charArr.length; i++) {
      char c = charArr[i];
      Integer integer = map.get(c);

      // 判断后面的一个大于前面的话，则是特殊组合，就减去当前值就好
      if (i != charArr.length - 1) {
        Integer nextInteger = map.get(charArr[i + 1]);
        if (integer < nextInteger) {
          sum -= integer;
        } else {
          sum += integer;
        }
      } else {
        sum += integer;
      }
    }

    return sum;
  }

}